package org.wgc.study.utils;

import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * Jackson JSON 工具类
 * 提供对象-JSON 转换、日期格式化、集合解析、字段过滤、树模型操作等功能
 */
public class JacksonUtils {

    private static final ObjectMapper mapper;
    private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

    static {
        mapper = new ObjectMapper();

        // 序列化时忽略 null 字段
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 反序列化时忽略未知字段
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        // 配置 Java 8 时间模块
        JavaTimeModule timeModule = new JavaTimeModule();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_TIME_FORMAT);
        timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
        timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));

        mapper.registerModule(timeModule);
    }

    /** 对象转 JSON 字符串 */
    public static String toJson(Object obj) {
        try {
            return mapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("对象转 JSON 失败", e);
        }
    }

    /** JSON 字符串转对象 */
    public static <T> T toObject(String json, Class<T> clazz) {
        try {
            return mapper.readValue(json, clazz);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON 转对象失败", e);
        }
    }

    /** JSON 转 List */
    public static <T> List<T> toList(String json, Class<T> elementClass) {
        try {
            return mapper.readValue(json,
                    mapper.getTypeFactory().constructCollectionType(List.class, elementClass));
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON 转 List 失败", e);
        }
    }

    /** JSON 转复杂对象（如 Map、嵌套结构） */
    public static <T> T toComplexObject(String json, TypeReference<T> typeReference) {
        try {
            return mapper.readValue(json, typeReference);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON 转复杂对象失败", e);
        }
    }

    /** 指定过滤字段进行序列化 */
    public static String toJsonWithFilter(Object obj, String filterName, String... fieldsToExclude) {
        try {
            FilterProvider filters = new SimpleFilterProvider()
                    .addFilter(filterName, SimpleBeanPropertyFilter.serializeAllExcept(fieldsToExclude));
            return mapper.writer(filters).writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON 序列化字段过滤失败", e);
        }
    }

    /** JSON 转 JsonNode */
    public static JsonNode toJsonNode(String json) {
        try {
            return mapper.readTree(json);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON 转 JsonNode 失败", e);
        }
    }

    /** 获取 JsonNode 中指定字段值 */
    public static String getNodeValue(JsonNode node, String fieldName) {
        JsonNode valueNode = node.get(fieldName);
        return valueNode != null ? valueNode.asText() : null;
    }

    /** 修改 JSON 中指定字段 */
    public static String modifyNode(String json, String fieldName, Object newValue) {
        try {
            ObjectNode node = (ObjectNode) mapper.readTree(json);
            if (newValue instanceof String) {
                node.put(fieldName, (String) newValue);
            } else if (newValue instanceof Integer) {
                node.put(fieldName, (Integer) newValue);
            } else if (newValue instanceof Boolean) {
                node.put(fieldName, (Boolean) newValue);
            } else if (newValue instanceof Double) {
                node.put(fieldName, (Double) newValue);
            } else {
                node.putPOJO(fieldName, newValue);
            }
            return node.toString();
        } catch (JsonProcessingException e) {
            throw new RuntimeException("修改 JSON 节点失败", e);
        }
    }
}
